﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;

namespace Client.Components
{
    // V 1.0.1 - 2022-08-25 09:56:15
    // 1 新增 UpdateDataFromNativeSettings ( 从 NativeSettings.config 读取配置更新到 UcSerialDeviceConfig界面 )
	// 2 新增 SaveUIData2NativeSettings ( 保存 UcSerialDeviceConfig界面的数据到 NativeSettings.config 文件 )

    /// <summary>
    /// Interaction logic for UcSerialDeviceConfig.xaml
    /// </summary>
    public partial class UcSerialDeviceConfig : UserControl
    {
        public UcSerialDeviceConfig()
        {
            InitializeComponent();
        }

        #region [DP]Title

        public static readonly DependencyProperty TitleProperty = DependencyProperty.Register
        (
            name: "Title",
            propertyType: typeof(string),
            ownerType: typeof(UcSerialDeviceConfig),
            validateValueCallback: null,
            typeMetadata: new PropertyMetadata
            (
                defaultValue: "串口设备配置",
                propertyChangedCallback: null,
                coerceValueCallback: null
            )
        );

        public string Title
        {
            get { return (string)GetValue(TitleProperty); }
            set { SetValue(TitleProperty, value); }
        }

        #endregion

        public bool IsValidated
        {
            get
            {
                if (this.ucDeviceConfig == null)
                {
                    return false;
                }

                return this.ucDeviceConfig.IsValidated;
            }
        }

        public string Error
        {
            get
            {
                if (this.ucDeviceConfig == null)
                {
                    return "UcNetworkDeviceConfigBase is null";
                }

                return this.ucDeviceConfig.Error;
            }
        }

        public object DeviceConfig
        {
            get
            {
                dynamic r = new System.Dynamic.ExpandoObject();
                r.PortName = ucDeviceConfig.PortName;
                r.BaudRate = ucDeviceConfig.BaudRate;
                r.DataBits = ucDeviceConfig.DataBits;
                r.Parity = ucDeviceConfig.Parity;
                r.StopBits = ucDeviceConfig.StopBits;

                r.ThreadSleep_BeforeRead = ucDeviceConfig.ThreadSleep_BeforeRead;

                r.Encoding = ucDeviceConfig.Encoding;

                return r;
            }
        }

        /// <summary>
        /// 从 NativeSettings.config 读取配置更新到 UcSerialDeviceConfig界面
        /// </summary>
        /// <param name="key_suffix">Key前缀, 例如 Scanner_PortName 就填写 Scanner即可</param>
        public void UpdateDataFromNativeSettings(string key_suffix)
        {
            string a1 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_PortName");
            string a2 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_BaudRate");
            string a3 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_DataBits");
            string a4 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_Parity");
            string a5 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_StopBits");
            string a6 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_ThreadSleep_BeforeReadExisting");
            string a7 = Common.ConfigHandler.GetValueFromNativeSettings($"{key_suffix}_Encoding");

            this.UpdateData(a1, a2, a3, a4, a5, a6, a7);
        }

        public void UpdateData
        (
            string portName = "", string baudRateStr = "", string dataBitsStr = "", string parityStr = "", string stopBitsStr = "",
            string threadSleep_BeforeReadExisting = "",
            string encoding = ""
        )
        {
            var ViewModel = this.DataContext as UcSerialDeviceConfig_ViewModel;

            // 遇到的坑 传过来的COM口号不在列表中, 设置 ViewModel.PortName == null
            ViewModel.PortName = ViewModel.PortNameList.FirstOrDefault(i => i == portName);

            try
            {
                ViewModel.BaudRate = ViewModel.BaudRateList.First(i => i.Value == int.Parse(baudRateStr));
            }
            catch (Exception) { }

            try
            {
                ViewModel.DataBits = ViewModel.DataBitsList.First(i => i.Value == int.Parse(dataBitsStr));
            }
            catch (Exception) { }

            try
            {
                ViewModel.Parity = ViewModel.ParityList.First(i => i.Value == Util.IO.SerialPortUtil.GetParity(parityStr));
            }
            catch (Exception) { }

            try
            {
                ViewModel.StopBits = ViewModel.StopBitsList.First(i => i.Value == Util.IO.SerialPortUtil.GetStopBits(stopBitsStr));
            }
            catch (Exception) { }

            try
            {
                ViewModel.ThreadSleep_BeforeRead = int.Parse(threadSleep_BeforeReadExisting);
            }
            catch (Exception) { }

            try
            {
                ViewModel.Encoding = ViewModel.EncodingList.First(i => i.BodyName == encoding);
            }
            catch (Exception) { }
        }

        /// <summary>
        /// 保存 UcSerialDeviceConfig界面的数据到 NativeSettings.config 文件
        /// </summary>
        /// <param name="key_suffix">Key前缀, 例如 Scanner_PortName 就填写 Scanner即可</param>
        public void SaveUIData2NativeSettings(string key_suffix)
        {
            var vm = this.DataContext as UcSerialDeviceConfig_ViewModel;

            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_PortName", vm.PortName);
            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_BaudRate", vm.BaudRate.XMLValue);
            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_DataBits", vm.DataBits.XMLValue);
            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_Parity", vm.Parity.XMLValue);
            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_StopBits", vm.StopBits.XMLValue);
            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_ThreadSleep_BeforeReadExisting", $"{vm.ThreadSleep_BeforeRead}");
            Common.ConfigHandler.SetValueToNativeSettings($"{key_suffix}_Encoding", vm.Encoding.BodyName);
        }
    }

    public class UcSerialDeviceConfig_ViewModel : BaseViewModel
    {
        #region Props

        private string _PortName;
        public string PortName
        {
            get { return _PortName; }
            set
            {
                _PortName = value;
                this.OnPropertyChanged(nameof(PortName));
            }
        }


        private List<string> _PortNameList;
        public List<string> PortNameList
        {
            get { return _PortNameList; }
            set
            {
                _PortNameList = value;
                this.OnPropertyChanged(nameof(PortNameList));
            }
        }



        private Util.IO.BaudRate _BaudRate;
        public Util.IO.BaudRate BaudRate
        {
            get { return _BaudRate; }
            set
            {
                _BaudRate = value;
                this.OnPropertyChanged(nameof(BaudRate));
            }
        }

        private List<Util.IO.BaudRate> _BaudRateList;
        public List<Util.IO.BaudRate> BaudRateList
        {
            get { return _BaudRateList; }
            set
            {
                _BaudRateList = value;
                this.OnPropertyChanged(nameof(BaudRateList));
            }
        }

        private Util.IO.DataBits _DataBits;
        public Util.IO.DataBits DataBits
        {
            get { return _DataBits; }
            set
            {
                _DataBits = value;
                this.OnPropertyChanged(nameof(DataBits));
            }
        }

        private List<Util.IO.DataBits> _DataBitsList;
        public List<Util.IO.DataBits> DataBitsList
        {
            get { return _DataBitsList; }
            set
            {
                _DataBitsList = value;
                this.OnPropertyChanged(nameof(DataBitsList));
            }
        }


        private Util.IO.Parity _Parity;
        public Util.IO.Parity Parity
        {
            get { return _Parity; }
            set
            {
                _Parity = value;
                this.OnPropertyChanged(nameof(Parity));
            }
        }


        private List<Util.IO.Parity> _ParityList;
        public List<Util.IO.Parity> ParityList
        {
            get { return _ParityList; }
            set
            {
                _ParityList = value;
                this.OnPropertyChanged(nameof(ParityList));
            }
        }


        private Util.IO.StopBits _StopBits;
        public Util.IO.StopBits StopBits
        {
            get { return _StopBits; }
            set
            {
                _StopBits = value;
                this.OnPropertyChanged(nameof(StopBits));
            }
        }

        private List<Util.IO.StopBits> _StopBitsList;
        public List<Util.IO.StopBits> StopBitsList
        {
            get { return _StopBitsList; }
            set
            {
                _StopBitsList = value;
                this.OnPropertyChanged(nameof(StopBitsList));
            }
        }


        private int _ThreadSleep_BeforeRead;
        public int ThreadSleep_BeforeRead
        {
            get { return _ThreadSleep_BeforeRead; }
            set
            {
                _ThreadSleep_BeforeRead = value;
                this.OnPropertyChanged(nameof(ThreadSleep_BeforeRead));
            }
        }



        private List<Encoding> _EncodingList;
        public List<Encoding> EncodingList
        {
            get { return _EncodingList; }
            set
            {
                _EncodingList = value;
                this.OnPropertyChanged(nameof(EncodingList));
            }
        }


        private Encoding _Encoding;
        public Encoding Encoding
        {
            get { return _Encoding; }
            set
            {
                _Encoding = value;
                this.OnPropertyChanged(nameof(Encoding));
            }
        }

        #endregion

        public UcSerialDeviceConfig_ViewModel()
        {
            initCMD();
            initData();
            resetDefault();
        }

        void initData()
        {
            this.PortNameList = Util.IO.SerialPortUtil.GetPortNameList();

            if (this.PortNameList != null && this.PortNameList.Count > 0)
            {
                this.PortName = this.PortNameList[0];
            }

            this.BaudRateList = Util.IO.SerialPortUtil.GetBaudRateList();
            this.DataBitsList = Util.IO.SerialPortUtil.GetDataBitsList();
            this.ParityList = Util.IO.SerialPortUtil.GetParityList();
            this.StopBitsList = Util.IO.SerialPortUtil.GetStopBitsList();

            Encoding[] t = new Encoding[2];
            t[0] = Encoding.UTF8;
            t[1] = Encoding.GetEncoding("gb2312");

            this.EncodingList = t.ToList();
        }

        void initCMD()
        {
            this.CMD_ResetDefault = new Command(resetDefault);
            this.CMD_RefreshPortNameList = new Command(refleshPortNameList);
        }

        #region Command ResetDefault

        public Command CMD_ResetDefault { get; private set; }

        void resetDefault()
        {
            resetSerialDevice();
            resetThreadSleep_BeforeReading();
            resetEncoding();
        }

        /// <summary>
        /// 重置串口设备配置
        /// </summary>
        void resetSerialDevice()
        {
            this.BaudRate = this.BaudRateList.First(i => i.XMLValue == "9600");
            this.DataBits = this.DataBitsList.First(i => i.XMLValue == "8");
            this.Parity = this.ParityList.First(i => i.XMLValue == "NONE");
            this.StopBits = this.StopBitsList.First(i => i.XMLValue == "ONE");
        }

        void resetThreadSleep_BeforeReading()
        {
            this.ThreadSleep_BeforeRead = 80;
        }

        void resetEncoding()
        {
            this.Encoding = this.EncodingList.First(i => i.BodyName == "utf-8");
        }

        #endregion

        #region Command RefreshPortNameList

        public Command CMD_RefreshPortNameList { get; private set; }

        void refleshPortNameList()
        {
            this.PortNameList = Util.IO.SerialPortUtil.GetPortNameList();
        }

        #endregion

    }
}
